package com.ming.mallchat.common.common.service;

import com.ming.mallchat.common.common.utils.AssertUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author 86150
 * @date 2023/10/07
 */
@Service
public class LockService {

    @Autowired
    private RedissonClient redissonClient;

    public <T> T executeWithLockThrows(String key, int waitTime, TimeUnit unit,SupplierThrow<T> supplier) throws Throwable {
        RLock lock = redissonClient.getLock("acquireItem" + key);
        boolean b = lock.tryLock(waitTime,unit);
        AssertUtil.isTrue(b, "操作频繁，请稍后再试");
        try {
            return supplier.get();
        } finally {
            lock.unlock();
        }
    }

    public <T> T executeWithLock(String key, int waitTime, TimeUnit unit, Supplier<T> supplier) throws Throwable {
        return executeWithLockThrows(key,waitTime,unit,supplier::get);
    }

    public <T> T executeWithLock(String key, Supplier<T> supplier) throws Throwable {
        return executeWithLock(key,-1,TimeUnit.MILLISECONDS,supplier);
    }

    @FunctionalInterface
    public interface SupplierThrow<T> {

        /**
         * Gets a result.
         *
         * @return a result
         */
        T get() throws Throwable;
    }

}
